package com.ljf.authority.domain.base;

import com.ljf.authority.enums.AuthorityBaseMenuPageMethodModeEnum;
import com.ljf.authority.enums.AuthorityBaseMenuTabulationLevelEnum;
import com.ljf.authority.infra.assembler.AuthorityBaseMenuTabulationAssembler;
import com.ljf.authority.vo.*;
import com.ljf.common.exception.ServiceException;
import com.ljf.common.utils.CollectionUtil;
import com.ljf.common.utils.StringUtil;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 菜单列表定义  基础服务
 *
 * @author LJF
 * @since 2024-10-17
 */
@Component
public class AuthorityBaseMenuTabulationBaseService {

    private final AuthorityBaseMenuTabulationAssembler ASSEMBLER = AuthorityBaseMenuTabulationAssembler.INSTANCE;

    /**
     * 构建树结构
     *
     * @param modelList
     * @param mainMenuDetailList
     * @param menuPageDetailList
     * @return
     * @throws ServiceException
     */
    public List<AuthorityBaseMenuTabulationMainMenuVO> buildTree(List<AuthorityBaseMenuTabulationVO> modelList, List<AuthorityBaseMainMenuDetailVO> mainMenuDetailList, List<AuthorityBaseMenuPageDetailVO> menuPageDetailList) throws ServiceException {
        if (CollectionUtil.isEmpty(modelList)) {
            return Collections.emptyList();
        }
        List<AuthorityBaseMenuTabulationIndexVO> modelIndexList = ASSEMBLER.toIndexVO(modelList);
        Map<String, AuthorityBaseMainMenuDetailVO> mainMenuDetailMap = Collections.emptyMap();
        if (CollectionUtil.isNotEmpty(mainMenuDetailList)) {
            mainMenuDetailMap = mainMenuDetailList.stream()
                    .collect(Collectors.toMap(AuthorityBaseMainMenuDetailVO::getCode, Function.identity(), (a, b) -> a));
        }
        Map<String, AuthorityBaseMenuPageDetailVO> menuPageDetailMap = Collections.emptyMap();
        if (CollectionUtil.isNotEmpty(menuPageDetailList)) {
            menuPageDetailMap = menuPageDetailList.stream()
                    .collect(Collectors.toMap(AuthorityBaseMenuPageDetailVO::getCode, Function.identity(), (a, b) -> a));
        }
        List<AuthorityBaseMenuTabulationIndexVO> mainMenuList = buildChildrenTree(
                modelIndexList, "", AuthorityBaseMenuTabulationLevelEnum.MAIN_MENU.getCode()
        );
        List<AuthorityBaseMenuTabulationMainMenuVO> resultList = new ArrayList<>();
        AuthorityBaseMenuTabulationMainMenuVO mainMenuVO;
        AuthorityBaseMainMenuDetailVO mainMenuDetailVO;
        for (AuthorityBaseMenuTabulationIndexVO menuTabulationVO : mainMenuList) {
            mainMenuDetailVO = mainMenuDetailMap.get(menuTabulationVO.getCode());
            mainMenuVO = ASSEMBLER.toMainMenuVO(menuTabulationVO, mainMenuDetailVO == null ? "" : mainMenuDetailVO.getPicCode());
            mainMenuVO.setChildren(
                    buildMenuClassificationTree(
                            mainMenuVO.getCode(),
                            modelIndexList,
                            menuPageDetailMap
                    )
            );
            mainMenuVO.setChildrenCount(mainMenuVO.getChildren().size());
            resultList.add(mainMenuVO);
        }
        return resultList;
    }

    /**
     * 构建权限按钮返回信息
     *
     * @param resultList
     * @param buttonDetailList
     */
    public void buildButton(List<AuthorityBaseMenuTabulationButtonVO> resultList, List<AuthorityBaseButtonDetailVO> buttonDetailList) {
        if (CollectionUtil.isEmpty(resultList) || CollectionUtil.isEmpty(buttonDetailList)) {
            return;
        }
        resultList.sort(Comparator.comparing(AuthorityBaseMenuTabulationVO::getSort));
        Map<String, AuthorityBaseButtonDetailVO> map = buttonDetailList.stream()
                .collect(Collectors.toMap(
                        AuthorityBaseButtonDetailVO::getCode,
                        Function.identity(),
                        (a, b) -> a)
                );
        for (AuthorityBaseMenuTabulationButtonVO vo : resultList) {
            if (StringUtil.isEmpty(vo.getCode())) {
                continue;
            }
            ASSEMBLER.toFillButtonInfo(vo, map.get(vo.getCode()));
        }
    }

    /**
     * 构建菜单方法名
     *
     * @param methodList
     * @param initMethods
     * @param destructionMethods
     */
    public void buildMenuMethod(List<AuthorityBaseMenuPageMethodVO> methodList, List<String> initMethods, List<String> destructionMethods) {
        if (CollectionUtil.isEmpty(methodList)) {
            return;
        }
        initMethods.addAll(
                methodList.stream()
                        .filter(one -> Objects.equals(one.getMode(), AuthorityBaseMenuPageMethodModeEnum.INIT_EXEC.getCode()))
                        .map(AuthorityBaseMenuPageMethodVO::getMethod)
                        .distinct()
                        .collect(Collectors.toList())
        );
        destructionMethods.addAll(
                methodList.stream()
                        .filter(one -> Objects.equals(one.getMode(), AuthorityBaseMenuPageMethodModeEnum.DESTRUCTION_EXEC.getCode()))
                        .map(AuthorityBaseMenuPageMethodVO::getMethod)
                        .distinct()
                        .collect(Collectors.toList())
        );
    }

    /**
     * 构建树结构-菜单分类
     *
     * @param code
     * @param modelList
     * @param menuPageDetailMap
     * @return
     * @throws ServiceException
     */
    private List<AuthorityBaseMenuTabulationMenuClassificationVO> buildMenuClassificationTree(String code, List<AuthorityBaseMenuTabulationIndexVO> modelList, Map<String, AuthorityBaseMenuPageDetailVO> menuPageDetailMap) throws ServiceException {
        List<AuthorityBaseMenuTabulationIndexVO> menuClassificationList = buildChildrenTree(
                modelList, code, AuthorityBaseMenuTabulationLevelEnum.MENU_CLASSIFICATION.getCode()
        );
        List<AuthorityBaseMenuTabulationMenuClassificationVO> resultList = ASSEMBLER.toMenuClassificationVO(
                menuClassificationList
        );
        for (AuthorityBaseMenuTabulationMenuClassificationVO menuClassificationVO : resultList) {
            menuClassificationVO.setChildren(
                    buildMenuPageTree(
                            menuClassificationVO.getCode(),
                            modelList,
                            menuPageDetailMap
                    )
            );
            menuClassificationVO.setChildrenCount(menuClassificationVO.getChildren().size());
        }
        return resultList;
    }

    /**
     * 构建树结构-页面
     *
     * @param code
     * @param modelList
     * @param menuPageDetailMap
     * @return
     * @throws ServiceException
     */
    private List<AuthorityBaseMenuTabulationMenuPageVO> buildMenuPageTree(String code, List<AuthorityBaseMenuTabulationIndexVO> modelList, Map<String, AuthorityBaseMenuPageDetailVO> menuPageDetailMap) throws ServiceException {
        List<AuthorityBaseMenuTabulationIndexVO> menuPageList = buildChildrenTree(
                modelList, code, AuthorityBaseMenuTabulationLevelEnum.MENU_PAGE.getCode()
        );
        List<AuthorityBaseMenuTabulationMenuPageVO> resultList = new ArrayList<>();
        AuthorityBaseMenuPageDetailVO menuPageDetailVO;
        for (AuthorityBaseMenuTabulationIndexVO menuTabulationVO : menuPageList) {
            menuPageDetailVO = menuPageDetailMap.get(menuTabulationVO.getCode());
            AuthorityBaseMenuTabulationMenuPageVO result = ASSEMBLER.toMenuPageVO(
                    menuTabulationVO,
                    menuPageDetailVO == null ? "" : menuPageDetailVO.getComponentUrl()
            );
            result.setChildrenCount(buildButtonTree(result.getCode(), modelList).size());
            resultList.add(result);
        }
        return resultList;
    }

    /**
     * 构建树结构-按钮
     *
     * @param code
     * @param modelList
     * @return
     * @throws ServiceException
     */
    private List<AuthorityBaseMenuTabulationIndexVO> buildButtonTree(String code, List<AuthorityBaseMenuTabulationIndexVO> modelList) throws ServiceException {
        return buildChildrenTree(
                modelList, code, AuthorityBaseMenuTabulationLevelEnum.BUTTON.getCode()
        );
    }

    /**
     * 构建子流程树
     *
     * @param modelList
     * @param pCode
     * @param level
     * @return
     * @throws ServiceException
     */
    private List<AuthorityBaseMenuTabulationIndexVO> buildChildrenTree(List<AuthorityBaseMenuTabulationIndexVO> modelList, String pCode, Integer level) throws ServiceException {
        if (CollectionUtil.isEmpty(modelList)) {
            return Collections.emptyList();
        }
        return modelList.stream()
                .filter(
                        one -> Objects.equals(one.getLevel(), level)
                                && one.getSort() != null
                                && StringUtil.equals(pCode, one.getPCode())
                ).sorted(Comparator.comparing(AuthorityBaseMenuTabulationIndexVO::getSort))
                .collect(Collectors.toList());
    }

}
